一個元素包含開始標籤、結束標籤、屬性及內容,例如: <Tag 屬性>內容</Tag>
。
常用標籤
標籤名稱 | 用途 |
---|
<h1> ~<h6>
| 標題<p>
|段落<a href="https://www.123.com">
|超連結<table>
|表格<tr>
|表格內的row<td>
|表格內的cell<br/>
|換行(無結束標籤)
常用屬性(Attributes)
屬性名稱 | 用途 |
---|
class
|標籤的類別(可重複)id
|標籤的id(不可重複)title
|標籤的顯示資訊style
|標籤的樣式data-*
|自行定義的屬性
在HTTP協定中,定義了多種不同的method做為服務的請求方法,近年來由於行動裝置的普及化,越來越多的產品及網站都提供了WebAPI服務,既然我們要擷取網頁內容,就必須知道對HTTP請求方式。
在HTTP 1.1的版本中定義了八種 Method (方法),如下所示:
常見的method為以下5種:
method | 意義 |
---|
GET|取得(想要的服務)的資料或是狀態。|
POST|如同填表般的行為,以新增一項資料。
PUT|利用更新的方式於"指定位置"新增一項資料。
PATCH|在現有的資料欄位中,增加或部分更新一筆新的資料。
DELETE|刪除指定資料。
更進一步了解請參閱W3C制定規範RFC 5789。另外在網頁與"資料庫"的操作過程中,也會經常聽到CRUD這個詞,CRUD是指新增(Create)、讀取(Read)、更新(Update)、刪除(Delete)的主要4個操作資料庫(如MySQL等)常用的功能。
/GET/items/9527
/POST/items
/PATCH/items/9527
/DELETE/items/9527
time.sleep()
增加間隔,如:
import time
print('----start----')
time.sleep(3)
print('----done----')
import time
import random
random_s = 1 + random.randint(0,2) #加入隨機秒數
print('----start----')
time.sleep( random_s)
print('----done----')
/robots.txt
查看,如https://www.facebook.com/robots.txt
及https://twitter.com/robots.txt
。都有寫明禁止爬取之處。robots.txt
只是表明不要到網站這些地方,許多 Web Scraping 自動化工具及服務會遵循(也可以關掉預設值)。requests.get()
抓取網頁原始碼,如您尚未安裝 requests
模組,請先在終端機執行 pip install requests
,記得結尾有 s
唷。import requests
res = requests.get('http://www.example.com/')
print(res.text[:500])
Requests
常用函數
response.status_code
response.encoding
response.text
res.encoding
#輸出 UTF-8
參閱Beautiful Soup 文件(此時最新版本為 4.9.0 )。
Beautiful Soup 是強大的 HTML 解析器,可創建一個 BeautifulSoup
物件,將網頁讀入。此時soup
的 datatype 為 bs4.BeautifulSoup
物件,此物件中包含了整個 HTML 文件的結構樹,有了這個結構樹之後,就可以輕鬆找出任何有興趣的資料了。如尚未安裝請執行 pip install beautifulsoup4
安裝模組,如為筆記本環境請加魔術指令 !
。
from bs4 import BeautifulSoup
soup = BeautifulSoup(res.text, "lxml")
type(soup)
#輸出 bs4.BeautifulSoup
下表列出了主要的超文本解析器,以及它們的優缺點:
解析器 | 使用方法 | 優勢 | 劣勢 |
---|
Python 標準庫| BeautifulSoup(markup,"html.parser")
|Python的內建標準庫、執行速度適中、文檔容錯能力強|Python 2.7.3及3.2.2之前的版本中文檔容錯能力差 lxml HTML 解析器|
BeautifulSoup(markup, "lxml") |速度快、文檔容錯能力強(通常用這個)|需要安装C語言庫 xml XML 解析器|
BeautifulSoup(markup , "xml")|速度快、唯一支持XML的解析器|需要安装C語言庫 html5lib |
BeautifulSoup(markup, "html5lib")` |最好的容錯性、以瀏覽器的方式解析文檔、生成HTML5格式的文檔|速度較慢、不依賴外部模組
輸出排版後的 HTML 程式碼
print(soup.prettify())
soup.find()
找一個標籤 tag,將回傳第一個被 tag 包圍的區塊,例如soup.find('p')
。
傳入的參數第一個通常是 tag 名稱,第二個引數若未指明屬性就代表 class 名稱,也可以直接使用 id 等屬性去定位區塊。定位到區塊後,可以取出其屬性與包含的字串值,接受的參數為soup.find(name=None, attrs={}, recursive=True, text=None, **kwargs)
。
以下程式顯示a
標籤內容、a
標籤的href
屬性內容,以及a
標籤的文字內容:
import requests
from bs4 import BeautifulSoup
res = requests.get('http://www.example.com/')
soup = BeautifulSoup(res.text, "lxml")
a = soup.find("a")
print(a) #<a href="https://www.iana.org/domains/example">More information...</a>
print(a["href"]) #https://www.iana.org/domains/example
print(a.text) #More information...
以下程式將 title
標籤抓出來,用 title.string
抓出其內容
title_tag = soup.title
print(title_tag) #<title>Example Domain</title>
print(title_tag.string) #Example Domain
取出節點屬性
get
,如果不用get
也可以擷取屬性,但不存在時會出現錯誤,有礙後續爬蟲執行。使用get
如無此屬性,回傳結果為none。其他詳細用法可參考 BeautifulSoup的官方文件
get()``,未搜尋到的結果回傳為
None`,不會報錯終止。soup.find_all()
,我全都要!
import requests
from bs4 import BeautifulSoup
res = requests.get('http://www.example.com/')
soup = BeautifulSoup(res.text, "lxml")
p_tags = soup.find_all("p")
print(p_tags)
for
迴圈囉:
p_tags = soup.find_all("p")
for tag in p_tags:
print(tag.string)
soup.find_all(["h1","p","a"])
:limit
參數限制搜尋數量,如: soup.find_all("p", limit=2)
,只有1個就可以改為 find()
就好。{k:v}
的樣式,如 soup.find_all("", {"class":"zzz"})
。soup.find_all(text="Example Domain")
:soup.select()
soup.slect()
的選取方式跟 jQuery 十分相似,是基於 CSS 的搜尋,如果您有 jQuery 基礎會學得相當親切亦用。class
就用 .
;搜尋 id
就用 #
。class
或 id
的屬性,用中括號 []
填入要搜尋的[屬性名稱]
、或[屬性名稱及其內容]
。
import requests
from bs4 import BeautifulSoup
res = requests.get('http://www.example.com/')
soup = BeautifulSoup(res.text, "lxml")
select_a = soup.select("a")
select_href1 = soup.select('[href]')
select_href2 = soup.select('[href="https://www.iana.org/domains/example"]')
#以下輸出結果一致,皆為[<a href="https://www.iana.org/domains/example">More information...</a>]
print(select_a)
print(select_href1)
print(select_href2)
select_a[0]["href"]
正規表達式對於精準抓取網頁的各種標籤及內文非常有幫助,解決了許多Xpath與CSS selector無法精確擷取的問題,有必要好好理解。
擷取的文句段落可以使用regex101嘗試,該網站亦可搜尋別人寫好的正規表達式。
意義 | 表示 | 範例 |
---|
Start|^
|123ABC /^1/
End|$
|123ABC /5$/
Range|[<Start>-End>]
|123ABC /^[0-2]/
Number|\d
|123ABC /^\d/
Character|\w
|123ABC /\w$/
Invisible Character|\s
|Tab, Space, Escape, …
Zero or One|+
|
Zero or More|*
|123ABC /\w+$/
One or More|?
|123ABC /[0-2]/
Named Group|(?P<name>expression)
|
Named Group|(?<name>expression)
|
Python 的正規表達是可使用內建的 re
模組:
re.findall()
函數。import re
pattern = "我寫好的 regular expression"
string = "我想要找的字串"
re.findall(pattern, string)
import requests
import re
res = requests.get('http://www.example.com/')
#找出html裡的超連結
pattern = r'href=\"(.*)\"|href=\'(.*)\'' #參閱https://regex101.com/r/uw6MLH/1
string = res.text
re.findall(pattern, string)[0][0]
這篇文章主要介紹網頁資料擷取常用的 requests
及 的 soup.find()
、 soup.find_all()
、 soup.select()
用法、正規表達式的 re.findall()
模組,已經可以實踐抓取許多網頁,但網路資料擷取/爬蟲基本上都要針對不同網站下功夫處理,時常伺服器為了反爬蟲也在更動屬性/標籤,下篇會包含實作,我們下篇見!